/*
 *    Copyright 2009-2021 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.reflection.property;

import java.lang.reflect.Field;

import org.apache.ibatis.reflection.Reflector;

/**
 * 属性复制器
 *
 * @author Clinton Begin
 */
public final class PropertyCopier {

  private PropertyCopier() {
    // Prevent Instantiation of Static Class
  }

  /**
   * 复制属性值
   *
   * @param type            指定类
   * @param sourceBean      源对象
   * @param destinationBean 目标对象
   * @author evan Date : 2021/10/11
   */
  public static void copyBeanProperties(Class<?> type, Object sourceBean, Object destinationBean) {

    // 定义一个父类类型
    // 将传入的指定类型赋值给父类类型
    // 复制属性时使用父类类型
    Class<?> parent = type;

    // 父类类型不为空
    // 这里有个将父类类型超类赋值给父类类型的动作
    while (parent != null) {

      // 获取类申明的属性, 不包含超类
      final Field[] fields = parent.getDeclaredFields();

      // 遍历属性
      for (Field field : fields) {
        try {
          try {

            // 将源对象的属性值赋值给目标对象
            field.set(destinationBean, field.get(sourceBean));
          } catch (IllegalAccessException e) {
            if (Reflector.canControlMemberAccessible()) {
              field.setAccessible(true);
              field.set(destinationBean, field.get(sourceBean));
            } else {
              throw e;
            }
          }
        } catch (Exception e) {
          // Nothing useful to do, will only fail on final fields, which will be ignored.
        }
      }
      // 将父类类型超类赋值给父类类型
      parent = parent.getSuperclass();
    }
  }

}
